home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-07-20 | 17.4 KB | 658 lines | [TEXT/CWIE] |
- //Copyright (c) 1997 Aidan Cully
- //All rights reserved
-
- #include "CLBaseWindow.h"
- #include "CLApplication.h"
- #include "CLMouseHandler.h"
- #include "CLGrowLayout.h"
- #include <LowMem.h>
- #include "CLWindowLayer.h"
- #include "CLWindowDrawer.h"
-
- //Difference between the border and the content. Can only be called when the window is open.
- void GetWindowDiffRect( WindowRef window, Rect *diffRect )
- {
- RgnHandle strucRgn, contRgn;
-
- strucRgn = NewRgn();
- contRgn = NewRgn();
- GetWindowStructureRgn( window, strucRgn );
- GetWindowContentRgn( window, contRgn );
- diffRect->top = (**strucRgn).rgnBBox.top-(**contRgn).rgnBBox.top;
- diffRect->left = (**strucRgn).rgnBBox.left-(**contRgn).rgnBBox.left;
- diffRect->right = (**strucRgn).rgnBBox.right-(**contRgn).rgnBBox.right;
- diffRect->bottom = (**strucRgn).rgnBBox.bottom-(**contRgn).rgnBBox.bottom;
- DisposeRgn( contRgn );
- DisposeRgn( strucRgn );
- }
-
- //TBaseWindow::RespondResizeSelf()
- // uses:
- // Use this function to adjust the contents of the window after it has been resized
- // in:
- // Rect oldRect:
- // This rectangle is the old size of the window
- // Rect newRect:
- // This rectangle is the new size of the window
- // out:
- // returns SInt8
- // kWindowSuccess: Everything's groovy..
- // kWindowNotInitializedErr: You forgot to call Init(), you dope!
- // side effects:
- // none, but maybe in your derived classes :-D
- SInt8 TBaseWindow::RespondResizeSelf( const Rect &oldRect, const Rect &newRect )
- {
- if( !mWindow )
- return( kWindowNotInitializedErr );
- mContent->TrySize( newRect );
- TMouseHandler::SGetMouse()->CalcMouseMoveRgn();
- GetDrawFocus();
- // ::InvalRect( &oldRect );
- if( mNeedWindowDrawers.MoveFirst() ) {
- TWindowDrawer *iter;
- do {
- mNeedWindowDrawers.GetData( iter );
- iter->DrawWindow( this );
- } while( mNeedWindowDrawers.MoveNext() );
- }
- mContent->Draw( this );
- ReleaseDrawFocus();
- }
-
- //TBaseWindow::TBaseWindow
- // uses:
- // The TBaseWindow constructor, initializes the window to an unusable state. To use the
- // window, call Init()
- // in:
- // SInt16 resID:
- // The resource ID of this window. Expect this to be replaced by a structure so that
- // I don't have to change the declaration for this function on every platform I use.
- // side effects:
- // The window is initialized to an unusable state.
- TBaseWindow::TBaseWindow( SInt16 resID, TWindowLayer *layer, TLayoutLeaf *content ):
- mhWinRes( resID ),
- mContent( content ),
- mWindow( 0l ),
- mOpen( 0 ),
- mActive( 0 ),
- mLayer( layer )
- {
- }
-
-
- //TBaseWindow::~TBaseWindow()
- // uses:
- // The class destructor. Do not delete a Window directly, rather call KillWindow().
- // side effects:
- // Low level details of killing the window.
- TBaseWindow::~TBaseWindow()
- {
- if( mLayer )
- mLayer->RemoveWindow( this );
- if( mContent ) {
- mContent->Close();
- delete mContent;
- }
- if( mWindow ) {
- DoHideWindow();
- ::DisposeWindow( mWindow );
- }
- }
-
- //TBaseWindow::GetDrawSelf()
- // see TDrawSlate::GetDrawSelf()
- Boolean TBaseWindow::GetDrawSelf()
- {
- if( !IsOpen() )
- return( false );
- ::GetPort( &mhOldPort );
- ::SetPort( mWindow );
- return( true );
- }
-
- //TBaseWindow::ReleaseDrawSelf()
- // see TDrawSlate::ReleaseDrawSelf()
- Boolean TBaseWindow::ReleaseDrawSelf()
- {
- ::SetPort( mhOldPort );
- return( true );
- }
-
- //TBaseWindow::DoMouseDown()
- // uses:
- // Handle a mouseDown inside of our window
- // in:
- // short partCode:
- // What part of the window the event took place in
- // EventRecord theEvent
- // Event data
- // out:
- // returns SInt8:
- // kWindowNotInitializedErr: You didn't call Init()!
- // kWindowInvalidPartCodeErr: The partCode passed in is invalid
- // kWindowSuccess: Everything's groovy.. yeah.
- // Other: Anything returned by one of our inner functions
- // side effects:
- // If the window wasn't in front, now it is. Other side effects would be determined in
- // subclasses
- void TBaseWindow::DoMouseDown( short partCode, const TMouseButtonEvent *theEvent )
- {
- if( !(mWindow && mOpen) )
- return;
- if( !IsActive() ) {
- SelectWindow();
- return; //Make sure our window is active before clicking in it.
- }
- if( theEvent->button )
- switch( partCode ) {
- case inContent:
- DoContentClick( theEvent );
- break;
- case inDrag:
- DoDrag( theEvent );
- break;
- case inGoAway:
- if( TrackGoAway( mWindow, theEvent->where ) )
- DoClose();
- break;
- case inGrow:
- DoGrow( theEvent );
- break;
- case inZoomIn:
- case inZoomOut:
- if( TrackBox( mWindow, theEvent->where, partCode ) )
- DoZoom( partCode, theEvent );
- break;
- case inDesk:
- ::SysBeep(0);
- break;
- }
- else if( partCode == inContent )
- DoContentClick( theEvent );
- }
-
- //SInt8 TBaseWindow::DoContentClick()
- // uses:
- // Handles a mouse event inside of us.
- // in:
- // EventRecord theEvent:
- // event data
- // out:
- // returns SInt8:
- // kWindowNotInitializedErr: You didn't call Init()
- // kWindowSuccess: everythings groovy
- // Other: determined by subclasses
- void TBaseWindow::DoContentClick( const TMouseButtonEvent *theEvent )
- {
- }
-
- //TBaseWindow::DoShowWindow()
- // uses:
- // Show this window
- // out:
- // returns SInt8:
- // kWindowNotInitializedErr: You didn't call Init()
- // kWindowSuccess: Everything's groovy..
- // side effects:
- // The window is visible
- SInt8 TBaseWindow::DoShowWindow()
- {
- Rect stdRect, tempRect;
-
- if( !IsOpen() ) {
- //::ShowWindow( mWindow );
- //This actually shows the window
- mLayer->AddWindow( this );
- stdRect = qd.screenBits.bounds;
- GetWindowDiffRect( mWindow, &tempRect );
- stdRect.top += ::GetMBarHeight()-tempRect.top;
- stdRect.bottom -= tempRect.bottom;
- stdRect.left -= tempRect.left;
- stdRect.right -= tempRect.right;
- ::InsetRect( &stdRect, 3, 3 );
- ::SetWindowStandardState( mWindow, &stdRect );
- mOpen = true;
- }
- return( kWindowSuccess );
- }
-
- //TBaseWindow::DoHideWindow()
- // uses:
- // Hide this window
- // out:
- // returns SInt8:
- // kWindowNotInitializedErr: You didn't call Init()
- // kWindowSuccess: Everything's groovy..
- // side effects:
- // The window is invisible
- SInt8 TBaseWindow::DoHideWindow()
- {
- if( !mWindow )
- return( kWindowNotInitializedErr );
- if( mOpen ) {
- mOpen=false;
- mLayer->RemoveWindow( this );
- }
- return( kWindowSuccess );
- }
-
- //TBaseWindow::DoUpdate()
- // uses:
- // Respond to update events
- // out:
- // returns SInt8:
- // kWindowNotInitializedErr: You didn't call Init()
- // kWindowSuccess: Everything's.. just fine.
- // Other: to be determined by subclasses.
- SInt8 TBaseWindow::DoUpdate()
- {
- int retVal;
- GrafPtr oldPort;
-
- if( !mWindow )
- return(kWindowNotInitializedErr);
- GetPort( &oldPort );
- BeginUpdate( mWindow );
- Draw();
- EndUpdate( mWindow );
- SetPort( oldPort );
- //if we've been exposed, it could mean that a system window we don't have control over has
- //changed positions, so the mouse moved region must be updated.
- //if( FrontWindow()==this )
- //TMouseHandler::SGetMouse()->CalcMouseMoveRgn();
- return( kWindowSuccess );
- }
-
- //TBaseWindow::DrawSelf()
- // uses:
- // Where the actual Window drawing takes place. Override this in your subclasses to
- // display content.
- // side effects:
- // The area inside of the window is erased.
- // Determined by subclasses
- void TBaseWindow::DrawSelf()
- {
- if( mNeedWindowDrawers.MoveFirst() ) {
- TWindowDrawer *iter;
- do {
- mNeedWindowDrawers.GetData( iter );
- iter->DrawWindow( this );
- } while( mNeedWindowDrawers.MoveNext() );
- }
- mContent->Draw( this );
- }
-
- void TBaseWindow::AddDrawer( TWindowDrawer *draw ) {
- if( mNeedWindowDrawers.FindIndex( draw )!=-1 )
- return;
- mNeedWindowDrawers.MoveLast();
- mNeedWindowDrawers.AddNext( draw );
- }
-
- //The area occupied by the GrowIcon and the scroll bars.
- void GetGrowRgn( const Rect &windowRect, RgnHandle copyTo ) {
- Rect tempRect;
- RgnHandle tempRgn1, tempRgn2;
-
- OpenRgn();
- tempRect.top = windowRect.bottom-15;
- tempRect.bottom = windowRect.bottom;
- tempRect.left = windowRect.left;
- tempRect.right = windowRect.right;
- FrameRect( &tempRect );
- tempRect.left = windowRect.right-15;
- tempRect.top = windowRect.top;
- tempRect.bottom = windowRect.bottom-15;
- FrameRect( &tempRect );
- CloseRgn( copyTo );
- }
-
- //TBaseWindow::DoGrow()
- // uses:
- // Used internally by TBaseWindow to handle a click in the grow box. This function will
- // be moved into a TSizeableLayout (or something like that) which will grow the window
- // and will also be able to handle size negotiations inside a window
- // in:
- // EventRecord &theEvent
- // The event which generated this grow call
- // out:
- // returns SInt8
- // kWindowNotInitializedErr: You didn't call Init()
- // kWindowSuccess: Everything's.. Just fine.
- void TBaseWindow::DoGrow( const TMouseButtonEvent *event )
- {
- long retval;
- Rect growRect, oldSize, newSize;
-
- if( !mWindow )
- return;
- growRect = mContent->GetLargestSize();
- OffsetRect( &growRect, -growRect.left, -growRect.top );
- growRect.left = 64;
- growRect.top = 64;
- growRect.right++;
- growRect.bottom++;
- retval = GrowWindow( mWindow, event->where, &growRect );
- if( retval )
- {
- oldSize = ::GetWindowPort( mWindow )->portRect;
- ::OffsetRect( &oldSize, -oldSize.left, -oldSize.top );
- ::SizeWindow( mWindow, retval&0x0000ffff, retval>>16, false );
- newSize = ::GetWindowPort( mWindow )->portRect;
- ::OffsetRect( &newSize, -newSize.left, -newSize.top );
- // GetDrawFocus();
- RespondResizeSelf( oldSize, newSize );
- // ReleaseDrawFocus();
- }
- }
-
- //TBaseWindow::DoDrag()
- // uses:
- // Used internally by TBaseWindow to react to a click in the dragging area of a window
- // in:
- // EventRecord theEvent
- // The event which caused the drag
- // out:
- // returns SInt8
- // kWindowNotInitializedErr: You didn't call Init()
- // kWindowSuccess: The window has been moved
- // side effects:
- // The window will be at a new position on the screen
- void TBaseWindow::DoDrag( const TMouseButtonEvent *theEvent )
- {
- Rect dragRect;
- RgnHandle theRgn;
- RGBColor col;
- col.red= 0; col.green= 0; col.blue= 0;
- ::RGBForeColor( &col );
-
- if( !mWindow )
- return;
- dragRect = qd.screenBits.bounds;
- //DragWindow() brings a window to the front. This doesn't mesh with Floating Windows.
- //if( !TFloatingWindow::sFloatList.MoveFirst() )
- // DragWindow( mWindow, theEvent->where, &dragRect );
- //else {
- //The strategy we employ here is simple: Call DragGrayRgn() and MoveWindow() to
- //simulate a call to DragWindow().
- //Get the region
- theRgn= ::NewRgn();
- ::GetWindowStructureRgn( mWindow, theRgn );
- Rect theRect;
- //This is important because MoveWindow moves the content region to the specified coords
- //when we obviously want to move relative to the structure region
- GetWindowDiffRect( mWindow, &theRect );
- GrafPtr oldPort, newPort;
- ::GetPort( &oldPort );
- newPort= TApplication::SCurApp()->GetGlobalPort();
- ::SetPort( newPort );
- //Now we do clipping
- RgnHandle above= ::NewRgn();
- ClipAbove( above );
- ::SetClip( above );
- //Drag the outline
- UInt32 dragRet= ::DragGrayRgn( theRgn, theEvent->where, &dragRect, &dragRect, noConstraint, 0l );
- //We're not going to draw all over the desktop anymore
- ::SetPort( oldPort );
- ::DisposeRgn( above );
- //::DisposeRgn( bigRgn );
- delete newPort;
- //Move the window to the coordinates we got (offset by the diffRect from before)
- if( dragRet!=(0x80008000) )
- ::MoveWindow( mWindow, (**theRgn).rgnBBox.left-theRect.left, (**theRgn).rgnBBox.top-theRect.top, false );
- //Clean up memory
- ::DisposeRgn( theRgn );
- TMouseHandler::SGetMouse()->CalcMouseMoveRgn();
- //}
- }
-
- void TBaseWindow::DoZoom( short partCode, const TMouseButtonEvent *theEvent )
- {
- Rect diffRect, stdState;
- if( partCode == inZoomOut )
- {
- GetWindowDiffRect( mWindow, &diffRect );
- stdState = mContent->GetLargestSize();
- OffsetRect( &stdState, -stdState.left, -stdState.top );
- OffsetRect( &stdState, -diffRect.left, -diffRect.top+GetMBarHeight() );
- if( stdState.right >= qd.screenBits.bounds.right )
- stdState.right = qd.screenBits.bounds.right;
- if( stdState.bottom >= qd.screenBits.bounds.bottom )
- stdState.bottom = qd.screenBits.bounds.bottom;
- stdState.right -= diffRect.right;
- stdState.bottom -= diffRect.bottom;
- SetWindowStandardState( mWindow, &stdState );
- }
- GrafPtr oldPort;
- Rect oldSize, newSize;
-
- if( !mWindow )
- return;
- GetPort( &oldPort );
- SetPort( mWindow );
- oldSize = ::GetWindowPort( mWindow )->portRect;
- /*if( TFloatingWindow::sFloatList.MoveFirst() ) {
- TFloatingWindow *floatWin;
- TFloatingWindow::sFloatList.GetData( floatWin );
- ::SendBehind( mWindow, floatWin->GetWindow() );
- ::HiliteWindow( mWindow, true );
- ZoomWindow( mWindow, partCode, false );
- }
- else*/
- ZoomWindow( mWindow, partCode, false );
- newSize = ::GetWindowPort( mWindow )->portRect;
- SetPort( oldPort );
- RespondResizeSelf( oldSize, newSize );
- }
-
- SInt8 TBaseWindow::MakeActive( Boolean active ) {
- SInt8 retVal= kWindowSuccess;
- if( !mWindow )
- return( kWindowNotInitializedErr );
- mActive= active;
- ::HiliteWindow( mWindow, active );
- if( mContent )
- retVal= mContent->MakeActive( active );
- //if( active )
- //TMouseHandler::SGetMouse()->CalcMouseMoveRgn();
- return( retVal );
- }
-
- SInt8 TBaseWindow::DoClose() {
- if( !mWindow )
- return( kWindowNotInitializedErr );
- return( DoHideWindow() );
- }
-
- SInt8 TBaseWindow::Init() {
- mWindow = ::GetNewCWindow( mhWinRes, 0l, (WindowRef)-1l );
- if( !mWindow )
- return( kWindowNotInitializedErr );
- ::SetWRefCon( mWindow, (unsigned long)this ); //Highly important code.
- //This is the only way we can get the class from the WindowRef.
- mOpen = false; //Everything starts out invisible.
-
- Rect rect= GetWindowPort( mWindow )->portRect; //Initialize our content
- ::OffsetRect( &rect, -rect.left, -rect.top );
-
- int var= ::GetWVariant( mWindow );
- switch( var ) {
- case documentProc:
- case zoomDocProc:
- mContent= new TGrowLayout( 0, mContent );
- mContent->Init();
- break;
- };
- mContent->AttachedToWindow( this, rect );
- return( kWindowSuccess );
- }
-
- SInt8 TBaseWindow::SetWTitle( const Str255 theString ) {
- if( !mWindow )
- return( kWindowNotInitializedErr );
- ::SetWTitle( mWindow, theString );
- return( kWindowSuccess );
- }
-
- SInt8 TBaseWindow::GetWTitle( Str255 theTitle )
- {
- if( !mWindow )
- return( kWindowNotInitializedErr );
- ::GetWTitle( mWindow, theTitle );
- return( kWindowSuccess );
- }
-
- void TBaseWindow::HandleMouse( TMouseButtonEvent *ev )
- {
- WindowRef window;
-
- SelectWindow();
- DoMouseDown( FindWindow( ev->where, &window ), ev );
- }
-
- void TBaseWindow::Draw()
- {
- if( GetDrawFocus() ) {
- DrawSelf();
- MarkChanged( GetWindowPort( mWindow )->portRect );
- ReleaseDrawFocus();
- }
- }
-
- void TBaseWindow::SelectWindow()
- {
- WindowRef floatWin;
- UInt32 data;
-
- //if( !TFloatingWindow::sFloatList.MoveFirst() ) {
- /* ::SelectWindow( mWindow );
- if( shFrontWindow ) {
- shFrontWindow->MakeActive( false );
- }
- shFrontWindow= this;
- MakeActive( true );
- return;*/
- mLayer->SelectWindow( this );
- //}
- /*TFloatingWindow::sFloatList.GetData( floater );
- floatWin= floater->GetWindow();
- ::SendBehind( mWindow, floatWin );
- if( shFrontWindow ) {
- shFrontWindow->MakeActive( false );
- }
- shFrontWindow= this;
- MakeActive( true );*/
- }
-
- void TBaseWindow::LocalToGlobal( Point *pt )
- {
- GrafPtr oldPort;
-
- ::GetPort( &oldPort );
- ::SetPort( mWindow );
- ::LocalToGlobal( pt );
- ::SetPort( oldPort );
- }
-
- void TBaseWindow::GlobalToLocal( Point *pt )
- {
- GWorldPtr globWorld, world;
- GDHandle globDev, dev;
- TApplication::SCurApp()->GetGlobalWorld( globWorld, globDev );
- ::GetGWorld( &world, &dev );
- ::SetGWorld( globWorld, globDev );
- GrafPtr( oldPort );
- ::GetPort( &oldPort );
- ::SetPort( mWindow );
- ::GlobalToLocal( pt );
- ::SetPort( oldPort );
- ::SetGWorld( world, dev );
- }
-
- void TBaseWindow::ClipAbove( RgnHandle ret )
- {
- if( !ret )
- return;
- GWorldPtr globWorld, world;
- GDHandle globDev, dev;
- GrafPtr globPort, port;
- ::GetGWorld( &world, &dev );
- TApplication::SCurApp()->GetGlobalWorld( globWorld, globDev );
- ::SetGWorld( globWorld, globDev );
- ::GetPort( &port );
- ::SetPort( TApplication::SCurApp()->GetGlobalPort() );
- RgnHandle oldClip= ::NewRgn();
- ::GetClip( oldClip );
- Rect bigRect;
- RgnHandle temp= ::NewRgn();
- ::SetRect( &bigRect, -32767, -32767, 32767, 32767 );
- ::RectRgn( temp, &bigRect );
- ::SetClip( temp );
- WindowRecord *win= (WindowRecord*)mWindow;
- ::ClipAbove( mWindow );
- ::GetClip( ret );
- ::SetClip( oldClip );
- ::DisposeRgn( oldClip );
- ::DisposeRgn( temp );
- ::SetPort( port );
- ::SetGWorld( world, dev );
- }
-
- void TBaseWindow::CalcMouseMove( const Point &where, RgnHandle moveRgn )
- {
- if( !moveRgn )
- return;
- Point ul;
- ul.h= 0; ul.v= 0;
- GrafPtr oldPort;
- ::GetPort( &oldPort );
- ::SetPort( mWindow );
- ::LocalToGlobal( &ul );
- ::SetPort( oldPort );
- if( !IsActive() ) {
- RgnHandle above= ::NewRgn();
- ::GetWindowStructureRgn( mWindow, moveRgn );
- ClipAbove( above );
- ::SectRgn( moveRgn, above, moveRgn );
- ::DisposeRgn( above );
- TMouseHandler::SGetMouse()->SetListener( this );
- return;
- }
- RgnHandle thisRgn= ::NewRgn();
- ::GetWindowStructureRgn( mWindow, thisRgn );
- RgnHandle tempRgn= ::NewRgn();
- ::GetWindowContentRgn( mWindow, tempRgn );
- ::DiffRgn( thisRgn, tempRgn, thisRgn );
- ClipAbove( tempRgn );
- ::HNoPurge( (Handle)tempRgn );
- ::SectRgn( tempRgn, thisRgn, thisRgn );
- if( ::PtInRgn( where, thisRgn ) ) {
- TMouseHandler::SGetMouse()->SetListener( this );
- ::DisposeRgn( tempRgn );
- ::CopyRgn( thisRgn, moveRgn );
- ::DisposeRgn( thisRgn );
- return;
- }
- ::GetWindowContentRgn( mWindow, moveRgn );
- if( ::PtInRgn( where, moveRgn ) ) {
- ::OffsetRgn( moveRgn, -ul.h, -ul.v );
- if( mContent ) {
- Point localPoint= where;
- localPoint.h-= ul.h;
- localPoint.v-= ul.v;
- mContent->CalcMouseMove( localPoint, moveRgn );
- }
- ::OffsetRgn( moveRgn, ul.h, ul.v );
- ::SectRgn( tempRgn, moveRgn, moveRgn );
- } else {
- ::DisposeRgn( moveRgn );
- moveRgn= 0;
- }
- ::HPurge( (Handle)tempRgn );
- ::DisposeRgn( tempRgn );
- ::DisposeRgn( thisRgn );
- }
-
- void TBaseWindow::HandleMouseMoved( TMouseEvent *, bool )
- {
- }